package events;

import org.omg.CORBA.BAD_PARAM;
import org.omg.CORBA.COMM_FAILURE;
import org.omg.CosEventChannelAdmin.TypeError;
import org.omg.CosEventComm.PushConsumerPOA;

/**
* Clase wrapper para un consumidor de eventos. Para hacer uso
* de esta clase hay que heredar de ella e implementar los metodos "push"
* y "disconnect_push_consumer". Las clases que heredan de esta tienen que
* llamar a su constructor.
*
* @author Carlos Rodriguez Dominguez
*/
public abstract class EventConsumer extends PushConsumerPOA {
	
	private final int RETRIES = 100;
	
	protected org.omg.CORBA.ORB orb; /**< Orbe asociado al consumidor de eventos */
	protected org.omg.CosEventChannelAdmin.EventChannel channel; /**< Canal de eventos */
	protected org.omg.CosEventChannelAdmin.ConsumerAdmin consumer_admin; /**< Administrador del consumidor de eventos */
  	protected org.omg.CosEventChannelAdmin.ProxyPushSupplier proxy_supplier; /**< Proxy con el emisor de eventos */
	
	/**
	* Constructor
	*
	* @param __orb Orbe de CORBA asociado al consumidor de eventos
	*/
	public EventConsumer(org.omg.CORBA.ORB __orb)
	{
		orb = __orb;
		
		create_consumer();
	}
	
	/**
	* Se desconecta del emisor de eventos
	*/
	protected void disconnect_from_push_supplier()
	{
		int i;
		
		for(i=0; i<RETRIES; i++) 
		{
			proxy_supplier.disconnect_push_supplier();
			break;
		}
	}
	
	/**
	* Crea el consumidor de eventos
	*/
	protected void create_consumer()
	{	
		try {
			org.omg.PortableServer.POA rootPoa;
			org.omg.CORBA.Object obj = orb.resolve_initial_references("RootPOA");
			rootPoa = org.omg.PortableServer.POAHelper.narrow(obj);
			
			org.omg.PortableServer.POAManager pman = rootPoa.the_POAManager();
			pman.activate();
			
			org.omg.CosNaming.NamingContext rootContext;
			obj = orb.resolve_initial_references("NameService");
			rootContext = org.omg.CosNaming.NamingContextHelper.narrow(obj);

			org.omg.CosNaming.NameComponent[] name = new org.omg.CosNaming.NameComponent[1];
			name[0] = new org.omg.CosNaming.NameComponent();
			name[0].id = "EventChannel";
			name[0].kind = "EventChannel";
			
			obj = rootContext.resolve(name);
			channel = org.omg.CosEventChannelAdmin.EventChannelHelper.narrow(obj);
		}
		catch(org.omg.CORBA.SystemException e) 
		{
			System.out.println(e.getMessage());
			System.exit(1);
		}
		catch(Exception ex)
		{
			ex.printStackTrace();
			System.exit(1);
		}

		int i;
		for (i=0; i<RETRIES; i++)
		{
			try {
				consumer_admin = channel.for_consumers();
				break;
			}
			catch (COMM_FAILURE ex) 
			{
				System.out.println("Fallo de conexion: Reintento"+(i+1)+" de "+RETRIES);
				if ((i+1) >= RETRIES)
				{
					System.exit(1);
				}
			}
		}
		
		for (i=0; i<RETRIES; i++)
	  	{
			try {
	        	proxy_supplier = consumer_admin.obtain_push_supplier();
	        	break;
			}
	    	catch (COMM_FAILURE ex) 
			{
				System.out.println("Fallo de conexion: Reintento"+(i+1)+" de "+RETRIES);
				if ((i+1) >= RETRIES)
				{
					System.exit(1);
				}
			}
		}

		for (i=0; i<RETRIES; i++)
	  	{
	     	try {
	        	proxy_supplier.connect_push_consumer(this._this(orb));
	        	break;
	     	}
	     	catch (BAD_PARAM ex) 
			{
				System.out.println(ex.getMessage());
			    System.exit(1);
	     	}
	     	catch (org.omg.CosEventChannelAdmin.AlreadyConnected ex) 
			{
				break;
	     	}
	     	catch (COMM_FAILURE ex) 
			{
				System.out.println("Fallo de conexion: Reintento"+(i+1)+" de "+RETRIES);
				if ((i+1) >= RETRIES)
				{
					System.exit(1);
				}
	     	}
	     	catch (TypeError ex)
	     	{
	     		System.out.println(ex.getMessage());
	     		System.exit(1);
	     	}
	  	}
	}

}
